package com.test.springsecurity.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.springsecurity.util.JWTUtil;
import com.test.springsecurity.util.ResponseResult;
import com.test.springsecurity.util.ResultStatus;
import com.test.springsecurity.util.TokenEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 作用是：得到token中的账号信息 然后通过账号信息得到用户信息（权限）
 * 然后生成authentication对象 放到springsecurity的上下文
 */
@Slf4j
@Component
public class JwtOnce extends OncePerRequestFilter {

    @Resource
    private UserDetailsService userDetailsService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取token
        String token = request.getHeader("authorization");

        log.info(token);

        if(requireAuth(request.getRequestURI())){


            ResponseResult<Object> responseResult = new ResponseResult<>();
            //设置响应头
            response.setContentType("application/json;charset=utf-8");
            responseResult.setCode(401);
            responseResult.setResultStatus(ResultStatus.NO_LOGIN);
            responseResult.setMessage("请登录后操作");

            String json  = new ObjectMapper().writeValueAsString(responseResult);
            //对token进行校验
            if(token==null || token.length()==0 || token.equals("null")){
                //返回结果 让用户去登录
                response.getWriter().write(json);
                return;
            }

            //程序执行到此处说明前端提供了token
            TokenEnum verify = JWTUtil.verify(token);
            if (verify==TokenEnum.TOKEN_SUCCESS){
                //设置响应头
                response.setContentType("application/json;charset=utf-8");
                //得到的账号
                String uname = JWTUtil.getUname(token);

                //得到用户的权限信息
                UserDetails userDetails = userDetailsService.loadUserByUsername(uname);

                //封装成一个token对象
                UsernamePasswordAuthenticationToken authenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());

                //设置在上下文中 表明用户已经登录了
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }else{
                //伪造或者过期 让去登录
                response.getWriter().write(json);
                return;
            }


        }
        filterChain.doFilter(request,response);

    }

    //判断请求的uri是否需要认证后请求
    private boolean requireAuth(String uri){
        //可以匿名访问的
        //将数组转换为集合
        List<String> urls = Arrays.asList(
           "auth/login","user/regist"
        );

        //记录是否需要认证
        AtomicBoolean flag = new AtomicBoolean(true);
        urls.forEach(str ->{

            if(uri.endsWith(str)){
                flag.set(false);
                return;
            }
        });
        return flag.get();
    }

}
